package mongo

import (
	"cgs-server/helper"
	"cgs-server/server/cgs/app/models"
	v1 "cgs-server/server/cgs/app/models/v1"
	"cgs-server/server/cgs/app/models/vo"
	"cgs-server/server/cgs/app/store"
	"cgs-server/server/model"
	"fmt"
	"go.mongodb.org/mongo-driver/bson"
)

type worksheetRows struct {
	db *helper.Mongo
}

func (w *worksheetRows) BatchDeleteRow(wr *models.WorksheetRow, user *model.User, opts v1.DeleteOptions) error {
	filter := opts.GetFilter()
	wr.ResolveFilter(wr, user, &filter)
	_, err := w.db.DeleteMany(wr.CollectionName(), filter)
	return err
}

func (w *worksheetRows) BatchUpdateRow(wr *models.WorksheetRow, user *model.User, opts v1.UpdateOptions) error {
	filter := opts.GetFilter()
	wr.ResolveFilter(wr, user, &filter)
	set := bson.M(wr.Data)
	wr.ResolveUpdateCondition(wr, user, &set)
	update := bson.M{
		"$set": set,
	}
	_, err := w.db.UpdateMany(wr.CollectionName(), filter, update)
	return err
}

func (w *worksheetRows) BatchAddRow(wr []*models.WorksheetRow, user *model.User, opts v1.CreateOptions) error {
	if len(wr) == 0 {
		return nil
	}
	collectionName := wr[0].CollectionName()
	docs := make([]interface{}, 0, len(wr))
	for _, row := range wr {
		row.ResolveEntity(row, user)
		docs = append(docs, row)
	}

	_, err := w.db.InsertMany(collectionName, docs)
	return err
}

func (w *worksheetRows) Count(wr *models.WorksheetRow, user *model.User, opts v1.CountOptions) (int64, error) {
	filter := opts.GetFilter()
	wr.ResolveFilter(wr, user, &filter)
	count, err := w.db.Count(wr.CollectionName(), filter)
	return count, err
}

func (w *worksheetRows) Save(wr *models.WorksheetRow, user *model.User, opts v1.CreateOptions) error {
	wr.ResolveEntity(wr, user)
	_, err := w.db.InsertOne(wr.CollectionName(), wr)
	return err
}

func (w *worksheetRows) Get(wr *models.WorksheetRow, user *model.User, opts v1.GetOptions) (*vo.WorksheetRow, error) {
	filter := bson.M{}
	if wr.RowId != "" {
		filter["rowId"] = wr.RowId
	}
	wr.ResolveFilter(wr, user, &filter)
	result := &vo.WorksheetRow{}
	find, err := w.db.FindOne(wr.CollectionName(), filter, result)
	if !find {
		return nil, fmt.Errorf("row not found: %s", wr.GetId())
	}
	return result, err
}

func (w *worksheetRows) Update(wr *models.WorksheetRow, user *model.User, opts v1.UpdateOptions) error {
	filter := bson.M{}
	if wr.RowId != "" {
		filter["rowId"] = wr.RowId
	} else {
		return fmt.Errorf("row id is required")
	}
	wr.ResolveFilter(wr, user, &filter)
	set := bson.M(wr.Data)
	wr.ResolveUpdateCondition(wr, user, &set)
	update := bson.M{
		"$set": set,
	}
	_, err := w.db.UpdateOne(wr.CollectionName(), filter, update)
	return err
}

func (w *worksheetRows) Delete(wr *models.WorksheetRow, user *model.User, opts v1.DeleteOptions) error {
	filter := bson.M{}
	if wr.RowId != "" {
		filter["rowId"] = wr.RowId
	} else {
		return fmt.Errorf("row id is required")
	}
	wr.ResolveFilter(wr, user, &filter)
	_, err := w.db.DeleteOne(wr.CollectionName(), filter)
	return err
}

func (w *worksheetRows) List(wr *models.WorksheetRow, user *model.User, opts v1.ListOptions) (*vo.WorksheetRowList, error) {
	filter := opts.GetFilter()
	wr.ResolveFilter(wr, user, &filter)
	results := &vo.WorksheetRowList{}
	err := w.db.FindMany(wr.CollectionName(), filter, results, opts.ResolveFindOptions())
	return results, err
}

func newWorksheetRowsStore(d *datastore) store.WorksheetRowsStore {
	return &worksheetRows{
		db: d.db,
	}
}
